﻿using UnityEngine;

namespace Inlycat
{
    /// <summary>
    /// 状态机
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    public class StateMachine<T>
    {
        /// <summary>
        /// 实体
        /// </summary>
        private T _owner;
        
        /// <summary>
        /// 当前状态
        /// </summary>
        private State<T> _currState;
        
        /// <summary>
        /// 前一个状态
        /// </summary>
        private State<T> _prevState;
        
        /// <summary>
        /// 全局状态
        /// </summary>
        private State<T> _globalState;

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="owner">实体</param>
        /// <param name="currState">当前状态</param>
        /// <param name="prevState">前一个状态</param>
        /// <param name="globalState">全局状态</param>
        public StateMachine(T owner, State<T> currState = null, State<T> prevState = null, State<T> globalState = null)
        {
            this._owner = owner;
            this._currState = currState;
            this._prevState = prevState;
            this._globalState = globalState;
        }

        /// <summary>
        /// 设置当前状态
        /// </summary>
        /// <param name="currState">状态</param>
        public void SetCurrentState(State<T> currState)
        {
            this._currState = currState;
        }

        /// <summary>
        /// 设置前一个状态
        /// </summary>
        /// <param name="currState">状态</param>
        public void SetPreviousState(State<T> prevState)
        {
            this._prevState = prevState;
        }

        /// <summary>
        /// 设置全局状态
        /// </summary>
        /// <param name="globalState">全局状态</param>
        public void SetGlobalState(State<T> globalState)
        {
            this._globalState = globalState;
        }

        /// <summary>
        /// 更新FSM
        /// </summary>
        /// <param name="deltaTime">时间增量</param>
        public void Update(float deltaTime = 0f)
        {
            if (_globalState != null) _globalState.Execute(_owner, deltaTime);
            if (_currState != null) _currState.Execute(_owner, deltaTime);
        }

        /// <summary>
        /// 改变状态
        /// </summary>
        /// <param name="newState">新状态</param>
        public void ChangeState(State<T> newState)
        {
            _prevState = _currState;
            _currState.Exit(_owner);
            _currState = newState;
            _currState.Enter(_owner);
        }

        /// <summary>
        /// 返回前一个状态
        /// </summary>
        public void RevertToPreviousState()
        {
            ChangeState(_prevState);
        }

        /// <summary>
        /// 获取当前状态
        /// </summary>
        /// <returns>当前状态</returns>
        public State<T> GetCurrentState()
        {
            return this._currState;
        }

        /// <summary>
        /// 获取前一个状态
        /// </summary>
        /// <returns>前一个状态</returns>
        public State<T> GetPreviousState()
        {
            return this._prevState;
        }

        /// <summary>
        /// 获取全局状态
        /// </summary>
        /// <returns>全局状态</returns>
        public State<T> GetGlobalState()
        {
            return this._globalState;
        }

        /// <summary>
        /// 处理消息
        /// </summary>
        /// <param name="telegram">消息数据</param>
        /// <returns>是否处理</returns>
        public bool HandleMessage(Telegram telegram)
        {
            if (_currState != null && _currState.OnMessage(telegram))
            {
                return true;
            }

            if (_globalState != null && _globalState.OnMessage(telegram))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判定当前状态
        /// </summary>
        /// <param name="sType">状态类型</param>
        /// <returns>是否在sType状态中</returns>
        public bool isInState(System.Type sType)
        {
            return (sType == _currState.GetType());
        }
    }
}

